package com.gitee.dolt.boot.decrypt;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import com.gitee.dolt.boot.properties.BootProperties;
import com.gitee.dolt.annotation.decrypt.Decrypt;
import com.gitee.dolt.core.base.entity.EncryptedReq;
import com.gitee.dolt.core.exception.DecryptException;
import com.gitee.dolt.core.jackson.JacksonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * @author LYH
 */
@Slf4j
@Aspect
@RequiredArgsConstructor
public class DecryptAspect {

    public final BootProperties bootProperties;

    @Pointcut("@annotation(com.gitee.dolt.annotation.decrypt.Decrypt)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if (ArrayUtil.isEmpty(args)) {
            throw new DecryptException(joinPoint.getSignature().getName() + "，参数为空");
        }
        EncryptedReq encryptedReq = null;
        for (Object obj : args) {
            if (obj instanceof EncryptedReq) {
                encryptedReq = (EncryptedReq) obj;
                break;
            }
        }
        if (encryptedReq == null) {
            throw new DecryptException(joinPoint.getSignature().getName() + "，参数中无待解密类");
        }
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Decrypt annotation = methodSignature.getMethod().getAnnotation(Decrypt.class);
        decryptAndVerify(encryptedReq, annotation.decryptedClass());
        return joinPoint.proceed();
    }

    private void decryptAndVerify(EncryptedReq encryptedReq, Class decryptedClass) {
        BootProperties.DecryptProperties decryptProperties = bootProperties.getDecrypt();
        RSA rsa = SecureUtil.rsa(decryptProperties.getRsaPri(), decryptProperties.getRsaPub());
        String data;
        try {
            String aesKey = rsa.decryptStr(encryptedReq.getEncryptedAes(), KeyType.PrivateKey);
            if (aesKey.length() != 16 && aesKey.length() != 32) {
                throw new DecryptException("aesKey不是16或32位");
            }
            AES aes = SecureUtil.aes(aesKey.getBytes());
            data = aes.decryptStr(encryptedReq.getEncryptedData());
            log.debug("解密串：{}", data);
        } catch (Exception e) {
            throw new DecryptException("解密失败：" + e.getMessage());
        }

        Object o = JacksonUtil.parse(data, decryptedClass);
        encryptedReq.setData(o);
    }

}
